﻿// owner 蒋家伟

#pragma once
#include "IDocument.h"
#include "ElementId.h"
#include "IElement.h"
#include "ElementIdGenerator.h"

namespace jsdk
{
    class Document : public IDocument
    {
        DEFINE_DRIVER_FROM(Document, IDocument)
    public:
        /// \ brief 通过序列化文件重构文档
        /// \ in loadPath 流化文件的地址
        /// \ return 文档对象
        static OwnerPtr<Document> create(const std::wstring& loadPath);

        /// \ brief 创建一个全新的文档
        static OwnerPtr<Document> createEmpty();


        /// \ brief 将一个element对象传入，此时对象还未生成ID。只会发出element增加事件
        /// \ note : 适用于运行时创建对象，或者合并对象。不适合加载对象，加载对象应该保障与序列化数据ID相同
        bool AddElement(OwnerPtr<IElement> opElement);

        /// \ brief 设置RunTimeID
        void setRunTimeId(RunTimeId runtimeId);

    public:
        // 继承IDocument
        virtual RunTimeId getRunTimeId() const override;
        virtual IElement* getElement(const ElementId& elementId) override;
        virtual const IElement* getElement(const ElementId& elementId) const override;
        virtual std::set<ElementId> getAllElementId() const override;
        virtual bool deleteElement(const ElementId& elementId) override;
        virtual bool deleteElements(const std::set<ElementId>& elementIds, std::set<ElementId>* pDeleteFailElementId) override;

        virtual bool save(const std::wstring& savePath) const;

    private:
        /// \ brief 仅插入到m_elementToElementUMap中，不做任何处理
        bool insertElement(const jsdk::ElementId& elementId, OwnerPtr<IElement> opElement);

    private:
        RunTimeId m_runTimeId{};                                                                      // 运行时的文档ID
        ElementIdGenerator m_idGenerator;                                                             // 文档的对象ID生成器
        std::unordered_map<jsdk::ElementId, OwnerPtr<IElement>, ElementHash> m_elementToElementUMap;  // ID与对象的集合
    };
}
